//standard includes
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include <sys/stat.h>
//local includes
#include "Oasis.h"
#include "functions.hpp"
#include "scanner.hpp"
#include "passone.hpp"
//initialization
using namespace std;
ofstream outfile;
//easier coding variables
string filepath;
//verbose mode variable
bool verbose;
//color mode variable
bool allow_color;
//output allow variable
bool allow_output = true;
//log_file variable
const char* log_file;
ofstream logfile;
//remember arguments are argv[>0]
//0 is what was used to call the function
//argc is the number of arguments
int main(int argc, char **argv) {
    //if there are no arguements output usage and quit
    if (!argv[1]) {
	    write("        Usage:"+white+" Oasis <input path> <output path> [flags...]","34",true);
        write("            type --help in if you want to see more information","0",true);
        return 0;
    }
    //save the arguement to a string so it can be tested
    const char* arg = argv[1];
    string args= arg;
    //if the arguement is --help then output help and quit
    if (args=="--help") {
	    write("        Usage:"+white+" Oasis [--help/--version] <input path> <output path> [flags...]","34",true);
        help("--help","outputs this message and then quits");
	help("--version","ouputs the version number and quits");
	newline
	help("-v","assemble in verbose mode");
	help("-c","output will be in color mode");
	help("-d","don't write output to file if exists");
	help("-l","writes the verbose output to the path pointed to by the next arguement");
        return 0;
    }
    //if arguement is --version then output version and quit
    if (args=="--version") {
	verbose=true;
	write("        Oasis version:"+white+" "+(string)VERSION+(string)nl,"1;34",true);
	write("        Author:"+white+" "+(string)AUTHOR,"1;34",true);
	write("        Contributor:"+white+" "+(string)CONTRIBUTOR,"1;34",true);
        return 0;
    }
    if(argv[3]){
	    for(int i=3;i<argc;i++){
		switch(argv[i][1]){
			case 'v':
				write("Verbose Flag Set","1;34");
				verbose = true;
				break;
			case 'c':
				allow_color = true;
				write("Color Flag Set","1;34");
				break;
			case 'd':
				allow_output = false;
				write("Output on exist disabled","1;34");
				break;
			case 'l':
				write("Logging to "+(string)argv[++i],"1;34");
				log_file = argv[i];
				logfile.open(log_file);
				break;
			default:
				write("Error! flag "+(string)argv[i]+" doesn't exist!","31");
				break;
		}
	}
    }
    string stringpath =  argv[1];
    filepath = stringpath.substr(0,stringpath.rfind(PSEP)+1);
    //create a counter to show how many lines there are in the file
    int file_line_amount;
    //create an string array with all the contents of the file in it
    vector<string> file_content;
    write("Getting file contents","1;34",true);
    if (read_file(file_content,file_line_amount,argv[1])) {
        write("Scanning for includes and including","1;34",true);
	//
	file_content.back() = file_content.back()+" ";
        //scan for any include files and then include them into the file_content
        if (!inc_scanner(file_content,file_line_amount)) {
            ewrite("Assembly Failed","1;31",true);
            return 1;
        }
        write("Scanning for Comments and removing","1;34",true);
        //checks for fully commented lines and removes them
        commented_scanner(file_content,file_line_amount);
        //checks for the rest of the comments
        comments_scanner(file_content,file_line_amount);
        //start first pass
        if(!pass_one(file_content,file_line_amount)){
		ewrite("Assembly Failed","1;31",true);
		return 1;
	}
        //write out how many lines the file contains
        //note: does not use my standard write() functin because
        //of how there are more then one things to write to one line
	write("Lines in file: "+itoa(file_line_amount));
        string path = argv[2];
        if (FileExists(path)) {
            string type = path.substr(path.rfind(".")+1,3);
            if (type=="z80"||type=="asm"||type=="inc") {
		write("Error! Output file is a *."+type+"! Not allowed to output as an existing *."+type,"1;31",true);
		ewrite("Assembly Failed","1;31",true);
                return 1;
            }
            else{
		if(!allow_output){
			write("Error! Output file "+path+" already exists!","1;31",true);
			ewrite("Assembly Failed","5;31",true);
			return 1;
		}	
		write("Warning! Output file "+path+" already exists!","33",true);
	    }
        }
	write_file(file_content,argv[2]);
	ewrite("Assembling completed","1;34",true);
        return 0;
    }
    else {
	    ewrite("Assembly Failed","5;31",true);
        return 1;
    }
}
